package com.moli.iov.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NumberUtil {

	private NumberUtil(){}

	public static Short toShort(Object obj){
		if(obj instanceof Short){
			return (Short)obj;
		}
		String value = String.valueOf(obj);
		if(value == null || "".equals(value)){
			return null;
		}
		return Short.valueOf(value);
	}
	public static Byte toByte(Object obj){
		if(obj instanceof Byte){
			return (Byte)obj;
		}
		String value = String.valueOf(obj);
		if(value == null || "".equals(value)){
			return null;
		}
		return Byte.valueOf(value);
	}
	public static Integer toInteger(Object obj){
		if(obj instanceof Integer){
			return (Integer)obj;
		}
		String value = String.valueOf(obj);
		if(value == null || "".equals(value)){
			return null;
		}
		return Integer.valueOf(value);
	}
	public static Long toLong(Object obj){
		if(obj instanceof Long){
			return (Long)obj;
		}
		String value = String.valueOf(obj);
		if(value == null || "".equals(value)){
			return null;
		}
		return Long.valueOf(value);
	}
	public static Float toFloat(Object obj){
		if(obj instanceof Float){
			return (Float)obj;
		}
		String value = String.valueOf(obj);
		if(value == null || "".equals(value)){
			return null;
		}
		return Float.valueOf(value);
	}
	public static Double toDouble(Object obj){
		if(obj instanceof Double){
			return (Double)obj;
		}
		String value = String.valueOf(obj);
		if(value == null || "".equals(value)){
			return null;
		}
		return Double.valueOf(value);
	}

	//10进制转16进制
	public static String intToHex(int n){
		char[] ch = new char[20];
		int nIndex = 0;
		while ( true ){
			int m = n/16;
			int k = n%16;
			if ( k == 15 ){
				ch[nIndex] = 'F';
			} else if ( k == 14 ){
				ch[nIndex] = 'E';
			} else if ( k == 13 ){
				ch[nIndex] = 'D';
			} else if ( k == 12 ){
				ch[nIndex] = 'C';
			} else if ( k == 11 ){
				ch[nIndex] = 'B';
			} else if ( k == 10 ){
				ch[nIndex] = 'A';
			} else{
				ch[nIndex] = (char)('0' + k);
			}

			nIndex++;
			if ( m == 0 ){
				break;
			}

			n = m;
		}
		StringBuilder sb = new StringBuilder();
		sb.append(ch, 0, nIndex);
		sb.reverse();
		return sb.toString();
	}

	/**
	 * 数字转字节
	 * @param value
	 * @param size  字节数组长度
	 * @return
	 */
	public static byte[] intToHexToByte(Long value, int size){
		String len = Long.toHexString(value);
		len = StringUtil.addZeroForNum(len, size);
		byte[] b_len = ByteUtils.hexStringToBytes(len);
		return b_len;
	}

	/**
	 * 数字转字节
	 * @param value
	 * @param size  内容数组长度
	 *          例：int类型 1 转byte[]，
	 * @return
	 */
	public static byte[] intToHexToByte(Integer value, int size){
		String len = Integer.toHexString(value);
		len = StringUtil.addZeroForNum(len, size);
		byte[] b_len = ByteUtils.hexStringToBytes(len);
		return b_len;
	}

	/**
	 * 利用正则表达式判断字符串是否是数字
	 * @param str
	 * @return
	 */
	public static boolean isNumeric(String str){
		Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
		return pattern.matcher(str).matches();
	}

	/**
	 *
	 *  将字符串转化为double类型，转化出错默认为defaultVal 值
	 *
	 * @param value
	 * @param defaultVal
	 */
	public static double stringToDouble(String value, double defaultVal) {
		if(StringUtil.isBlank(value)){
			return defaultVal;
		}
		double rs = defaultVal;
		try {
			rs = Double.parseDouble(value);
		} catch (NumberFormatException e) {
			return defaultVal;
		}
		return rs;

	}


	private static final int DEF_DIV_SCALE = 10;

	public static BigDecimal round(BigDecimal decimal) {
		return new BigDecimal(Math.round(decimal.doubleValue()));
	}

	public static BigDecimal nullToZero(BigDecimal num) {
		if (num == null) {
			return new BigDecimal("0");
		}
		return num;
	}

	public static Long nullToZero(Long num) {
		if (num == null) {
			return new Long("0");
		}
		return num;
	}

	public static BigDecimal nullToZero(String num) {
		if (num == null) {
			return new BigDecimal("0");
		}
		return new BigDecimal(num);
	}

	public static Integer nullToZero(Integer num) {
		if (num == null) {
			return new Integer("0");
		}
		return num;
	}

	public static boolean isNumber(String num) {
		if (num == null) {
			return false;
		}
		Pattern p = Pattern.compile("\\d+");
		Matcher m = p.matcher(num);
		return m.matches();
	}

	public static boolean isNumberForImport(String num) {
		Pattern p = Pattern.compile("(\\d+)|(\\d+.{1}\\d+)");
		Matcher m = p.matcher(num);
		if (m.matches()) {
			/** 是小数且小数位不为0 */
			Float fNum = Float.parseFloat(num);
			return fNum.floatValue() == fNum.longValue();
		}
		return false;
	}

	public static boolean isFloat(String num) {
		Pattern p = Pattern.compile("(\\d+)|(\\d+.{1}\\d+)");
		Matcher m = p.matcher(num);
		return m.matches();
	}

	public static boolean isInteger(String num) {
		Pattern p = Pattern.compile("(\\d+)");
		Matcher m = p.matcher(num);
		return m.matches();
	}

	/**
	 * 有指定小数位
	 * @param num
	 * @param floatnum
	 * @return
	 */
	public static boolean isFloat(String num, int floatnum) {
		if (floatnum == 0) {
			return isInteger(num);
		}
		Pattern p = Pattern.compile("(\\d+)|(\\d+.{1}\\d{0," + floatnum + "})");
		Matcher m = p.matcher(num);
		return m.matches();
	}

	/**
	 * 提供精确的加法运算。
	 *
	 * @param v1
	 *            被加数
	 * @param v2
	 *            加数
	 * @return 两个参数的和
	 */
	public static BigDecimal add(BigDecimal v1, BigDecimal v2) {
		BigDecimal sum = new BigDecimal(0);
		// 设一个不为0的值
		if (v1 == null || v2 == null) {
			if (v1 == null && v2 == null) {
				return sum;
			}
			return v1 == null ? v2 : v1;
		}
		BigDecimal b1 = new BigDecimal(Double.toString(v1.doubleValue()));
		BigDecimal b2 = new BigDecimal(Double.toString(v2.doubleValue()));
		return b1.add(b2);
	}

	/**
	 * 提供精确的减法运算。
	 *
	 * @param v1
	 *            被减数
	 * @param v2
	 *            减数
	 * @return 两个参数的差
	 */
	public static BigDecimal sub(BigDecimal v1, BigDecimal v2) {
		BigDecimal b1 = new BigDecimal("0");
		if (v1 != null) {
			b1 = new BigDecimal(Double.toString(v1.doubleValue()));
		}
		BigDecimal b2 = new BigDecimal("0");
		if (v2 != null) {
			b2 = new BigDecimal(Double.toString(v2.doubleValue()));
		}
		return b1.subtract(b2);
	}

	/**
	 * 比较两个数大小
	 *
	 * @param v1
	 *            第一个数字
	 * @param v2
	 *            第二个数字
	 * @return 大于 还回 1 、等于还回 0 、小于 还回 -1
	 */
	public static int compare(BigDecimal v1, BigDecimal v2) {
		int intValue = 0;
		Double d1 = v1.doubleValue();
		Double d2 = v2.doubleValue();
		if (d1 > d2) {
			intValue = 1;
		}
		if (d1 == d2) {
			intValue = 0;
		}
		if (d1 < d2) {
			intValue = -1;
		}
		return intValue;
	}

	/**
	 * 提供精确的乘法运算。
	 *
	 * @param v1
	 *            被乘数
	 * @param v2
	 *            乘数
	 * @return 两个参数的积
	 */
	public static BigDecimal mul(BigDecimal v1, BigDecimal v2) {
		if (v1 == null || v2 == null) {
			return new BigDecimal(0);
		}
		BigDecimal b1 = new BigDecimal(Double.toString(v1.doubleValue()));
		BigDecimal b2 = new BigDecimal(Double.toString(v2.doubleValue()));

		return b1.multiply(b2);
	}

	/**
	 * 提供精确的乘法运算。
	 *
	 * @param v1
	 *            被乘数
	 * @param v2
	 *            乘数
	 * @return 两个参数的积
	 */
	public static BigDecimal mul(Long v1, BigDecimal v2) {
		if (v1 == null || v2 == null) {
			return new BigDecimal(0);
		}
		BigDecimal b1 = new BigDecimal(Double.toString(v1.doubleValue()));
		BigDecimal b2 = new BigDecimal(Double.toString(v2.doubleValue()));
		return b1.multiply(b2);
	}

	/**
	 * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后10位，以后的数字四舍五入。
	 *
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @return 两个参数的商
	 */
	public static BigDecimal div(BigDecimal v1, BigDecimal v2) {
		return div(v1, v2, DEF_DIV_SCALE);
	}

	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字四舍五入。
	 *
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @param scale
	 *            表示表示需要精确到小数点以后几位。
	 * @return 两个参数的商
	 */
	public static BigDecimal div(BigDecimal v1, BigDecimal v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b1 = new BigDecimal(Double.toString(v1.doubleValue()));
		BigDecimal b2 = new BigDecimal(Double.toString(v2.doubleValue()));
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * 提供精确的小数位四舍五入处理。
	 *
	 * @param v
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @return 四舍五入后的结果
	 */
	public static BigDecimal round(BigDecimal v, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b = new BigDecimal(Double.toString(v.doubleValue()));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * 数字、货币格式化
	 * @version 2011-9-21 下午09:19:39
	 * @param pattern
	 * @param number
	 * @return
	 */
	public static String numberFormat(String pattern, BigDecimal number) {
		String numberStr = null;
		if (number == null) {
			return "";
		}
		try {
			if (pattern == null || pattern.equals("")) {
				numberStr = new DecimalFormat("#0.00##").format(number.doubleValue());
			} else {
				numberStr = new DecimalFormat(pattern).format(number.doubleValue());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return numberStr;
	}

	/**
	 * 精确到小数位后两位
	 */
	public static String isDouble(String num) {
		if (num.equals("-") || StringUtil.isBlank(num)) {
			return "-";
		} else {
			DecimalFormat decimalFormat = new DecimalFormat("#.00");
			return decimalFormat.format(Double.valueOf(num));
		}
	}

	/**
	 * 返回负数
	 * @param num
	 * @return
	 */
	public static BigDecimal negative(BigDecimal num) {
		return mul(num, new BigDecimal(-1));
	}

	/**
	 * 获取随机数
	 * @param bound
	 * @return
	 */
	public static int nextInt(int bound){
		Random random = new Random();
		return random.nextInt(bound);
	}


}
